import numpy as np
import config
n = config.n
# 解码函数
def decode_schedule(X):
    times = np.array([
        [2, 4, 6, 4, 4, 6, 5, 3, 2, 3, 5, 6],
        [2, 5, 5, 3, 3, 5, 5, 2, 5, 5, 6, 2],
        [3, 4, 4, 4, 4, 3, 4, 4, 4, 4, 4, 4],
        [4, 3, 4, 6, 3, 2, 4, 7, 1, 3, 3, 5],
        [5, 4, 2, 5, 1, 3, 6, 5, 2, 4, 5, 4],
        [2, 3, 3, 3, 3, 3, 4, 3, 3, 7, 4, 6],
        [3, 4, 4, 6, 4, 3, 3, 4, 3, 8, 8, 7],
        [2, 5, 2, 5, 6, 9, 3, 3, 6, 6, 6, 6],
        [3, 4, 5, 8, 5, 5, 5, 5, 4, 5, 4, 5]
    ]).T
    n, m = X.shape # 工件数，工序数
    schedule = []  # 存储解码后的调度方案
    machine_end_times = np.zeros((m, times.shape[1]))  # 存储每台机器的结束时间
    job_end_times = np.zeros(n)  # 存储每个工件的结束时间

    for j in range(m):
        if j == 0:
            # 第一道工序，按照原先的排序方式
            work_order = sorted([(int(X[i][j]), X[i][j] - int(X[i][j]), i) for i in range(n)], key=lambda x: (x[0], x[1]))
        else:
            # 其他工序，先按照上一工序的结束时间排序，相同结束时间的工件再按照小数部分排序
            work_order = sorted([(int(X[i][j]), X[i][j] - int(X[i][j]), i, job_end_times[i]) for i in range(n)], key=lambda x: (x[3], x[0], x[1]))

        for order in work_order:
            machine = order[0]
            job = order[2]
            # 最早的开始时间应该是机器上一次的结束时间与工件上一次的结束时间中的较大值
            start_time = max(machine_end_times[j][machine-1], job_end_times[job])
            finish_time = start_time + times[job][machine-1]
            schedule.append((job+1, j+1, machine, start_time, finish_time))
            machine_end_times[j][machine-1] = finish_time
            job_end_times[job] = finish_time

    return schedule
#返回单个基因的具体方案
def toString(X):
    sch = decode_schedule(X)
    for s in sch:
        print(f"工件{s[0]} 在工序{s[1]} 使用机台{s[2]}，开始时间：{s[3]}，结束时间：{s[4]}")
# 返回单个基因的最长时间
def calc(X):
    # print(X)
    sch = np.array(decode_schedule(X)).reshape(3,n,5)[2][:,-1]
    return sch.max()
X = np.array([
    [1.3, 3.4, 5.1],
    [1.8, 4.6, 5.6],
    [2.3, 4.9, 6.7],
    [1.5, 3.1, 6.2]
])
X = np.array([
    [2.3, 3.4, 5.1],
    [3.8, 4.6, 5.6],
    [3.3, 4.9, 6.7],
    [1.5, 4.1, 6.2],
    [3.5, 6.1, 8.2],
    [3.5, 6.1, 8.2],
    [3.5, 6.1, 8.2],
    [3.5, 6.1, 8.2],
    [3.5, 6.1, 8.2],
    [3.5, 6.1, 8.2],
    [3.5, 6.1, 8.2],
    [3.5, 6.1, 8.2]
])
